import SwiftUI
import ARKit


struct ContentView: View {
    
    var body: some View {
        VStack {
            ScenekitView()
                .ignoresSafeArea()
        }
        .onAppear(){
            playAudio2(forResource: "linebegin", ofType: "mp3")
            playAudio(forResource: "ing", ofType: "mp3")
        }
    }
}




struct ScenekitView: UIViewControllerRepresentable {
 
    func makeUIViewController(context: Context) -> some UIViewController {
        let vc = ScenekitClass()
    
        return vc
    }
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
    

}


public   var canTap: Bool = true
class ScenekitClass: UIViewController {
    var roateLeftButton: UIButton!
    var roateRightButton: UIButton!
    var tipsImageView: UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
    var tipsButton: UIButton!
    var PassOneRoadLogic = RoadLogic()
    var returnButton: UIButton!
    var nextButton: UIButton!
    var nodeArry = [SCNNode]()
    var arry = [String]()
    var newArry = [String]()
    var scnView:SCNView!
    var scn:SCNScene!
    var scnNode:SCNNode!
    var currentMaterial: SCNMaterial!
    var scnNodeArry = [SCNNode]()
    var number = 0
    var roateOrNot: Bool = false
    var currtentZPosition: CGFloat!
    var cameraNode:SCNNode!
    var nowPass = 1
    
    var showCount = 1
    override func viewDidLoad() {
        PassOneRoadLogic.roadNameArry()
        
        let doubleTapFingers = UITapGestureRecognizer(target: self, action: #selector(judgeRoateOrNot))
        doubleTapFingers.numberOfTapsRequired = 2
        doubleTapFingers.numberOfTouchesRequired = 1
        let threeTapFingers = UITapGestureRecognizer(target: self, action: #selector(leftRoate))
        threeTapFingers.numberOfTapsRequired = 1
        threeTapFingers.numberOfTouchesRequired = 2
        setupView()
        setupMaterial()
        setupTips()
        self.view.addGestureRecognizer(doubleTapFingers)
        self.view.addGestureRecognizer(threeTapFingers)
        
    }
    //MARK: 基础配置
    func setupView() {
        switch nowPass {
        case 1:
            PassOneRoadLogic.roadNameArry()
            arry = [String]()
            newArry = [String]()
            scnView = SCNView(frame: view.frame)
            scn = SCNScene(named: scnName.passOne.rawValue)
            scn.background.contents = "Resources/background.png"
            scnView.scene = scn
            scnNode = SCNNode()
            scnNode = scn.rootNode.childNode(withName: "Main", recursively: true)
            scnNode.geometry?.materials.first?.transparency = 0.2
            //        scnNode.transform = SCNMatrix4MakeTranslation(0.282, 0, -0.527)
            currtentZPosition = CGFloat(scnNode.position.y)
            setupMaterial()
            tipsImageView.image = UIImage(named: "tips.001")
            tipsImageView.contentMode = .scaleAspectFill
            tipsImageView.alpha = 0
            setupCamera()
            let jointNode = scnNode.childNode(withName: "joint", recursively: true)
            for i in PassOneRoadLogic.passOneJoint {
                jointNode?.childNode(withName: i, recursively: false)?.isHidden = true
            }
       
            //Create transition effect
            view.addSubview(scnView)
            view.addSubview(tipsImageView)
            setupButton()
            setupTips()
          
        case 2:
            arry = [String]()
            newArry = [String]()
            scnView = SCNView(frame: view.frame)
            scn = SCNScene(named: scnName.passTwo.rawValue)
            scn.background.contents = "Resources/background.png"
            scnView.scene = scn
            scnNode = SCNNode()
            scnNode = scn.rootNode.childNode(withName: "Main", recursively: true)
            scnNode.geometry?.materials.first?.transparency = 0.2
            //        scnNode.transform = SCNMatrix4MakeTranslation(0.282, 0, -0.527)
            currtentZPosition = CGFloat(scnNode.position.y)
            setupMaterial()
            tipsImageView.image = UIImage(named: "tips.002")
            tipsImageView.contentMode = .scaleAspectFill
            let jointNode = scnNode.childNode(withName: "joint", recursively: true)
            for i in PassOneRoadLogic.passTwoJoint {
                jointNode?.childNode(withName: i, recursively: false)?.isHidden = true
            }
            
            setupCamera()
          
            //Create transition effect
            view.addSubview(scnView)
            view.addSubview(tipsImageView)
            setupTips()
            setupButton()
          
        case 3:
            
            arry = [String]()
            newArry = [String]()
            scnView = SCNView(frame: view.frame)
            scn = SCNScene(named: scnName.passThree.rawValue)
            scn.background.contents = "Resources/background.png"
            scnView.scene = scn
            scnNode = SCNNode()
            scnNode = scn.rootNode.childNode(withName: "Main", recursively: true)
            scnNode.geometry?.materials.first?.transparency = 0.2
            //        scnNode.transform = SCNMatrix4MakeTranslation(0.282, 0, -0.527)
            currtentZPosition = CGFloat(scnNode.position.y)
            setupMaterial()
            tipsImageView.image = UIImage(named: "tips.003")
            tipsImageView.contentMode = .scaleAspectFill
            tipsImageView.alpha = 0
            let jointNode = scnNode.childNode(withName: "joint", recursively: true)
            
            for i in PassOneRoadLogic.passThreeJoint {
                jointNode?.childNode(withName: i, recursively: false)?.isHidden = true
            }
             
            setupTips()
            setupCamera()
           
            //Create transition effect
            view.addSubview(scnView)
            view.addSubview(tipsImageView)
            setupTips()
            setupButton()
       
        default:
            break
        }
        
        
    }
    func setupTips() {
        tipsButton = UIButton(frame: CGRect(x: UIScreen.main.bounds.width - CGFloat(120), y: 30, width: 100, height: 100))
        tipsButton.setImage(UIImage(named: "tipsbuttom"), for: .normal)
        tipsButton.contentMode = .scaleAspectFit
        tipsButton.addTarget(self, action: #selector(showTips), for: .touchUpInside)
 
        view.addSubview(tipsButton)
    }
    
    @objc func showTips() {
        showCount += 1
     print(showCount)
        if showCount % 2  != 0 {
            print("alpha = 0")
            tipsImageView.alpha = 0
        } else {
            print("alpha = 1")
            tipsImageView.alpha = 1
            
        }
       
    }
  
    // MARK: -Update
    
    func updateView(){
        
    }
    // Add Camera
    func setupCamera() {
        cameraNode = scn.rootNode.childNode(withName: "camera", recursively: false)
        
        print(cameraNode.position)
        
    }
    
    // Change Material
    func setupMaterial() {
        currentMaterial = SCNMaterial()
        currentMaterial.diffuse.contents = "Resources/Start.PNG"
    }
    
    
    
    @objc func judgeRoateOrNot() {
        if canTap == true {
            //            scnNode.runAction(SCNAction.repeatForever(SCNAction.rotateTo(x: CGFloat(scnNode.position.x), y: currtentZPosition + CGFloat(90), z: CGFloat(scnNode.position.z) , duration: 0.5, usesShortestUnitArc: true)))
            scnNode.runAction(SCNAction.rotate(by: 360*CGFloat.pi/180, around: SCNVector3(x: 0, y: 1, z: -0), duration: 2))
            currtentZPosition+=CGFloat(90)
            print(currtentZPosition)
        }
//        if nowPass == 1 {
//            if canTap != true {
//                nowPass = 2
//                setupView()
//            }
//        } else if nowPass == 2 {
//            if canTap != true {
//                nowPass = 3
//                setupView()
//            }
//
//        }
        
    }
    @objc func leftRoate() {
        if canTap == true {
            //            scnNode.runAction(SCNAction.repeatForever(SCNAction.rotateTo(x: CGFloat(scnNode.position.x), y: currtentZPosition - CGFloat(90), z: CGFloat(scnNode.position.z) , duration: 0.5, usesShortestUnitArc: true)))
            //
            
            
            currtentZPosition-=CGFloat(90)
            print(currtentZPosition)
        } else {
            print("Success")
        }
        
    }
    
    func setupButton() {
     
        nextButton = UIButton(frame: CGRect(x: view.frame.width - 150, y: view.frame.height - CGFloat(150) , width: 100, height: 100))
        returnButton = UIButton(frame: CGRect(x: 50, y: view.frame.height - CGFloat(150), width: 100, height: 100))
        roateRightButton = UIButton(frame: CGRect(x: 300, y: view.frame.height - CGFloat(150), width: 100, height: 100))
        roateLeftButton = UIButton(frame: CGRect(x: view.frame.width - 400, y: view.frame.height - CGFloat(150), width: 100, height: 100))
        

        switch nowPass {
        case 1:
           
            let returnImage = UIImage(named: "resetb")
            returnButton.setBackgroundImage(returnImage, for: .normal)
            returnButton.contentMode = .scaleAspectFill
            returnButton.addTarget(self, action: #selector(returnBack), for: .touchUpInside)
            let nextImage = UIImage(named: "nextb")
            nextButton.setBackgroundImage(nextImage, for: .normal)
            nextButton.contentMode = .scaleAspectFill
            nextButton.addTarget(self, action: #selector(nextLevel), for: .touchUpInside)
            nextButton.isHidden = true
        case 2:
            let returnImage = UIImage(named: "resetb")
            returnButton.setBackgroundImage(returnImage, for: .normal)
            returnButton.contentMode = .scaleAspectFill
            returnButton.addTarget(self, action: #selector(returnBack), for: .touchUpInside)
            let nextImage = UIImage(named: "nextb")
            nextButton.setBackgroundImage(nextImage, for: .normal)
            nextButton.contentMode = .scaleAspectFill
            nextButton.addTarget(self, action: #selector(nextLevel), for: .touchUpInside)
            nextButton.isHidden = true
        case 3:
            
         
            let returnImage = UIImage(named: "resetb")
            returnButton.setBackgroundImage(returnImage, for: .normal)
            returnButton.contentMode = .scaleAspectFill
            returnButton.addTarget(self, action: #selector(returnBack), for: .touchUpInside)
            let nextImage = UIImage(named: "nextb")
            nextButton.setBackgroundImage(nextImage, for: .normal)
            nextButton.contentMode = .scaleAspectFill
            nextButton.addTarget(self, action: #selector(nextLevel), for: .touchUpInside)
            nextButton.isHidden = true
            let roateRightImage = UIImage(named: "rightb")
            roateRightButton.setBackgroundImage(roateRightImage, for: .normal)
            roateRightButton.contentMode = .scaleAspectFill
            roateRightButton.addTarget(self, action: #selector(roateRight), for: .touchUpInside)
            let roateLeftImage = UIImage(named: "leftb")
            roateLeftButton.setBackgroundImage(roateLeftImage, for: .normal)
            roateLeftButton.contentMode = .scaleAspectFill
            roateLeftButton.addTarget(self, action: #selector(roateLeft), for: .touchUpInside)
            
           
        case 4:
            let returnImage = UIImage(named: "resety")
            returnButton.setBackgroundImage(returnImage, for: .normal)
            returnButton.contentMode = .scaleAspectFill
            returnButton.addTarget(self, action: #selector(returnBack), for: .touchUpInside)
            let nextImage = UIImage(named: "nextb")
            nextButton.setBackgroundImage(nextImage, for: .normal)
            nextButton.contentMode = .scaleAspectFill
            nextButton.addTarget(self, action: #selector(nextLevel), for: .touchUpInside)
            nextButton.isHidden = true
        case 5:
            let returnImage = UIImage(named: "resetg")
            returnButton.setBackgroundImage(returnImage, for: .normal)
            returnButton.contentMode = .scaleAspectFill
            returnButton.addTarget(self, action: #selector(returnBack), for: .touchUpInside)
        default:
            print("over down")
        }
       
        view.addSubview(returnButton)
        view.addSubview(nextButton)
        view.addSubview(roateRightButton)
        view.addSubview(roateLeftButton)
    }
    
    @objc func roateRight() {
        scnNode.runAction(SCNAction.rotate(by: 90*CGFloat.pi/180, around: SCNVector3(0, 1, 0), duration: 2))
    }
    @objc func roateLeft() {
        scnNode.runAction(SCNAction.rotate(by: -(90*CGFloat.pi/180), around: SCNVector3(0, 1, 0), duration: 2))
    }
    @objc func nextLevel() {
        switch nowPass {
        case 1:
            nowPass = 2
            setupView()
        case 2:
            nowPass = 3
            setupView()
        default:
            break
        }
    }
    @objc func returnBack() {
        newArry = [String]()
        arry = [String]()
        for  i in PassOneRoadLogic.logicDictionariesOne.values  {
            for j in i {
                scnNode.childNode(withName: j, recursively: true)?.isHidden = false
            }
           
        }
        for i in  PassOneRoadLogic.logicDictionariesOne.keys {
            scnNode.childNode(withName: i, recursively: true)?.geometry?.materials.first?.diffuse.contents = "Resources/Zhuan.png"
        }
        let childNodes = scnNode.childNode(withName: "joint", recursively: true)?.childNodes
        for i in  (childNodes)!{
            i.isHidden = true
        }
        
        updateView()
      
    }
    
    
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: scnView)
            let hitResult = scnView.hitTest(location, options: nil)
            
            if let result = hitResult.first {
//                print(result.node.name!)
                canTap = false
                //添加自动补点...
                
                arry.append(result.node.name!)
                nodeArry.append(result.node)
                newArry = arry.filterDuplicates({$0})
                print(newArry)
                
                switch nowPass {
                case 1:
                    print("1")
                case 2:
                    if result.node.name == "road_6"  {
                   
                        scnNode.childNode(withName: "road_16", recursively: true)?.isHidden = true
                    }
                    
                    if result.node.name == "road_12" {
                        scnNode.childNode(withName: "edge_111", recursively: true)?.isHidden = true
                    }
                    
                case 3:
                    let jointNode = scnNode.childNode(withName: "joint", recursively: true)
                    let jointDictionariereThree = [" Start":["joint_01"],"road_3":["joint_2"],"road_29":["joint5"], "road_7":["joint_03"], "road_10":["joint_04"], "road_12":["joint_05"], "road_15":["joint_06"], "road18":["joint_07"], "road_21":["joint_08"], "road_4":["joint_09"], "road_28":["joint3"], "edge_82":["joint6"], "edge_33":["joint4"]]
                    
                   
                default:
                    print("X")
                }
                if PassOneRoadLogic.roadName.contains(result.node.name!) == true || PassOneRoadLogic.PassTwoRightRoad.contains(result.node.name!)   {
                    playAudio(forResource: "dong", ofType: "mp3")
                    
                        SCNTransaction.begin()
                        SCNTransaction.animationDuration = 1.0
                        result.node.geometry?.materials.first?.diffuse.contents = currentMaterial.diffuse.contents
                        result.node.geometry?.firstMaterial?.emission.contents = UIColor.white
                        SCNTransaction.completionBlock = {
                            SCNTransaction.begin()
                            SCNTransaction.animationDuration = 1.0
                            result.node.geometry?.firstMaterial?.emission.contents = UIColor.black
                            SCNTransaction.commit()
                        }
                        SCNTransaction.commit()
                    }
                    if PassOneRoadLogic.PassOnewRightRoad.contains(result.node.name!) == true {
                        arry.append(result.node.name!)
                        nodeArry.append(result.node)
                        newArry = arry.filterDuplicates({$0})
                       
                    }
                if PassOneRoadLogic.PassTwoRightRoad.contains(result.node.name!) == true {
                    arry.append(result.node.name!)
                    nodeArry.append(result.node)
                    newArry = arry.filterDuplicates({$0})
                }
            
                    
                
             
           
                PassOneRoadLogic.turnOrNot(pass: nowPass, isInflectionPoint: result.node.name!, node: scnNode)
                
                let setNewArry = Set(newArry)
//                print(newArry)
                if setNewArry == Set(PassOneRoadLogic.PassOnewRightRoad) {
                    nextButton.isHidden = false
                    for i in PassOneRoadLogic.PassOnewRightRoad {
                        let node = scn.rootNode.childNode(withName: i, recursively: true)
                        let material = node?.geometry?.firstMaterial
                        SCNTransaction.begin()
                        SCNTransaction.animationDuration = 2
                        material?.emission.contents = UIColor.white
                        SCNTransaction.completionBlock = {
                            SCNTransaction.begin()
                            SCNTransaction.animationDuration = 2
                            material?.emission.contents = UIColor.black
                            SCNTransaction.commit()
                        }
                        SCNTransaction.commit()
                    }
                                        
                    // Add rotate animation
                    print("scnNode rotate")
                    let rotateActionOne = SCNAction.rotateTo(x: CGFloat(scnNode.position.x), y: CGFloat(scnNode.position.y) + CGFloat(180*CGFloat.pi/180), z: CGFloat(scnNode.position.z), duration: 2, usesShortestUnitArc: false)
                    let rotateActionTwo = SCNAction.rotateTo(x: CGFloat(scnNode.position.x), y: CGFloat(scnNode.position.y) + CGFloat(360*CGFloat.pi/180), z: CGFloat(scnNode.position.z), duration: 2)
                    //                    scnNode.runAction(SCNAction.group([rotateActionOne,rotateActionTwo]))
                    
                    scnNode.runAction(SCNAction.rotate(by: 360*CGFloat.pi/180, around: SCNVector3(x: 0, y: 1, z: -0), duration: 2))
                    
                    
                    
                    
                    
                    
                                        let alert = UIAlertController(title: "🎉", message: "You Win \n Touch Double click the screen to enter the next level", preferredStyle: .alert)
                                        let alertAction = UIAlertAction(title: "Next Level", style: .default)

                                        alert.addAction(alertAction)
                                        present(alert, animated: true, completion: nil)
                                        print(setNewArry.count)
                                        print(PassOneRoadLogic.isRight.toggle())
                    
                }
                
                if setNewArry == Set(PassOneRoadLogic.PassTwoRightRoad) {
                 
                    for i in PassOneRoadLogic.PassTwoRightRoad {
                        let node = scn.rootNode.childNode(withName: i, recursively: true)
                        let material = node?.geometry?.firstMaterial
                        SCNTransaction.begin()
                        SCNTransaction.animationDuration = 2
                        material?.emission.contents = UIColor.white
                        SCNTransaction.completionBlock = {
                            SCNTransaction.begin()
                            SCNTransaction.animationDuration = 2
                            material?.emission.contents = UIColor.black
                            SCNTransaction.commit()
                        }
                        SCNTransaction.commit()
                    }
                                        
                   print("_______________sucesss______________")
                 
                    
                    
                    
                    
                    
                                        let alert = UIAlertController(title: "🎉", message: "You Win \n Touch Double click the screen to enter the next level", preferredStyle: .alert)
                                        let alertAction = UIAlertAction(title: "Next Level", style: .default)

                                        alert.addAction(alertAction)
                                        present(alert, animated: true, completion: nil)
                                        print(setNewArry.count)
                                        print(PassOneRoadLogic.isRight.toggle())
                    
                }
                
            }
        }
    }
    
    
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            
            let location = touch.location(in: scnView)
            let hitResult = scnView.hitTest(location, options: nil)
            if let result = hitResult.first {
                //                print(result.node.name!)
                //                arry.append(result.node.name!)
                //                newArry = arry.filterDuplicates({$0})
                
                
            }
            
        }
    }
    
    
    
}

extension Array {
    
    // 去重
    func filterDuplicates<E: Equatable>(_ filter: (Element) -> E) -> [Element] {
        var result = [Element]()
        for value in self {
            let key = filter(value)
            if !result.map({filter($0)}).contains(key) {
                result.append(value)
            }
        }
        return result
    }
}
